import express from 'express';
import cors from 'cors';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
import { createLogger, format, transports } from 'winston';
import { createServer } from 'http';
import { WebSocketServer, WebSocket } from 'ws';
import deviceRoutes from './routes/deviceRoutes';
import authRoutes from './routes/auth.routes';
import jwt from 'jsonwebtoken';
import { config } from './config';

// 加载环境变量
dotenv.config();

const logger = createLogger({
  level: 'info',
  format: format.combine(
    format.timestamp(),
    format.json()
  ),
  transports: [
    new transports.Console(),
    new transports.File({ filename: 'app.log' })
  ]
});

const app = express();
const server = createServer(app);
const wss = new WebSocketServer({ server });

// WebSocket连接处理
wss.on('connection', (ws: WebSocket, req) => {
  try {
    // 从 URL 参数中获取 token
    const url = new URL(req.url || '', `http://${req.headers.host}`);
    const token = url.searchParams.get('token');

    if (!token) {
      ws.close(1008, '未提供认证令牌');
      return;
    }

    // 验证 token
    const decoded = jwt.verify(token, config.jwtSecret) as { userId: string };
    if (!decoded.userId) {
      ws.close(1008, '无效的认证令牌');
      return;
    }

    // 将用户ID存储在 WebSocket 连接中
    (ws as any).userId = decoded.userId;
    logger.info(`WebSocket 连接已建立，用户ID: ${decoded.userId}`);

    // 处理接收到的消息
    ws.on('message', (message: string) => {
      try {
        const { type, data } = JSON.parse(message);
        
        switch (type) {
          case 'heartbeat':
            // 处理心跳消息
            ws.send(JSON.stringify({ type: 'heartbeat_ack', data: { timestamp: Date.now() } }));
            break;
            
          case 'device_info':
            // 处理设备信息
            logger.info(`收到设备信息: ${JSON.stringify(data)}`);
            break;
            
          default:
            logger.warn(`未知的消息类型: ${type}`);
        }
      } catch (error) {
        logger.error('处理 WebSocket 消息时出错:', error);
      }
    });

    ws.on('error', (error: Error) => {
      logger.error('WebSocket 错误:', error);
    });

    ws.on('close', () => {
      logger.info(`WebSocket 连接已关闭，用户ID: ${(ws as any).userId}`);
    });
  } catch (error) {
    logger.error('WebSocket 认证错误:', error);
    ws.close(1008, '认证失败');
  }
});

// 广播消息给特定用户的所有连接
export const broadcastToUser = (userId: string, type: string, data: any) => {
  const message = JSON.stringify({ type, data });
  wss.clients.forEach((client: WebSocket) => {
    if (client.readyState === WebSocket.OPEN && (client as any).userId === userId) {
      client.send(message);
    }
  });
};

// 广播消息给所有连接的客户端
export const broadcast = (type: string, data: any) => {
  const message = JSON.stringify({ type, data });
  wss.clients.forEach((client: WebSocket) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(message);
    }
  });
};

// 广播设备状态变化
export const broadcastDeviceStatus = (deviceId: string, status: 'online' | 'offline', metadata: any) => {
  const message = JSON.stringify({
    type: 'device_status_broadcast',
    data: {
      deviceId,
      status,
      timestamp: new Date().toISOString(),
      metadata: {
        ...metadata,
        lastSeen: new Date().toISOString()
      }
    }
  });

  wss.clients.forEach((client: WebSocket) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(message);
    }
  });
};

// 中间件
app.use(cors({
  origin: '*',
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
  credentials: true,
  exposedHeaders: ['Content-Type', 'Authorization']
}));
app.use(express.json());

// 数据库连接
mongoose.connect(config.mongoUri, {
  serverSelectionTimeoutMS: 30000,
  socketTimeoutMS: 45000,
  connectTimeoutMS: 30000,
  maxPoolSize: 10,
  minPoolSize: 5,
  retryWrites: true,
  retryReads: true,
  heartbeatFrequencyMS: 10000,
  autoIndex: true,
})
  .then(() => {
    logger.info('Connected to MongoDB');
  })
  .catch((error) => {
    logger.error('MongoDB connection error:', error);
    process.exit(1);
  });

// 添加数据库连接事件监听
mongoose.connection.on('error', (error) => {
  logger.error('MongoDB connection error:', error);
});

mongoose.connection.on('disconnected', () => {
  logger.warn('MongoDB disconnected');
});

mongoose.connection.on('reconnected', () => {
  logger.info('MongoDB reconnected');
});

// 路由
app.use('/api/devices', deviceRoutes);
app.use('/api/auth', authRoutes);

// 健康检查接口
app.get('/api/health', (req, res) => {
  res.status(200).json({ status: 'ok' });
});

// 错误处理中间件
app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
  logger.error(err.stack);
  res.status(500).json({ error: 'Something went wrong!' });
});

const PORT = config.port;
server.listen(PORT, () => {
  logger.info(`Server is running on port ${PORT}`);
});

export default app; 